package tablut;

import java.util.ArrayList;

public class Plateau {
	Case[][] plateau;
	Pion[] pionsBlancs, pionsNoirs;
	CarteInfluence carte;
	
	Plateau() {
		System.out.println("### Initialisation du plateau ... ###");
		
		plateau = new Case[IJoueur.TAILLE][IJoueur.TAILLE];
		pionsNoirs = new Pion[16];
		pionsBlancs = new Pion[9];
		
		for(int i = 0; i < IJoueur.TAILLE; ++i) {
			for(int j = 0; j < IJoueur.TAILLE; ++j)
				plateau[i][j] = new Case(i, j, Case.NORMAL);
		}
		
		plateau[3][0].type = Case.SORTIE;
		plateau[4][0].type = Case.SORTIE;
		plateau[5][0].type = Case.SORTIE;
		plateau[0][3].type = Case.SORTIE;
		plateau[8][3].type = Case.SORTIE;
		plateau[0][4].type = Case.SORTIE;
		plateau[4][4].type = Case.TRONE;
		plateau[8][4].type = Case.SORTIE;
		plateau[0][5].type = Case.SORTIE;
		plateau[8][5].type = Case.SORTIE;
		plateau[3][8].type = Case.SORTIE;
		plateau[4][8].type = Case.SORTIE;
		plateau[5][8].type = Case.SORTIE;
		
		pionsNoirs[0] = plateau[3][0].p = new PionSoldat(IJoueur.NOIR, 0, 0, 3, 2, plateau[3][0], this);
		pionsNoirs[1] = plateau[4][0].p = new PionSoldat(IJoueur.NOIR, 0, 0, 0, 0, plateau[4][0], this);
		pionsNoirs[2] = plateau[5][0].p = new PionSoldat(IJoueur.NOIR, 0, 2, 3, 0, plateau[5][0], this);
		pionsNoirs[3] = plateau[4][1].p = new PionSoldat(IJoueur.NOIR, 0, 4, 0, 4, plateau[4][1], this);
		pionsNoirs[4] = plateau[0][3].p = new PionSoldat(IJoueur.NOIR, 2, 3, 0, 0, plateau[0][3], this);
		pionsNoirs[5] = plateau[8][3].p = new PionSoldat(IJoueur.NOIR, 2, 0, 0, 3, plateau[8][3], this);
		pionsNoirs[6] = plateau[0][4].p = new PionSoldat(IJoueur.NOIR, 0, 0, 0, 0, plateau[0][4], this);
		pionsNoirs[7] = plateau[1][4].p = new PionSoldat(IJoueur.NOIR, 4, 0, 4, 0, plateau[1][4], this);
		pionsNoirs[8] = plateau[7][4].p = new PionSoldat(IJoueur.NOIR, 4, 0, 4, 0, plateau[7][4], this);
		pionsNoirs[9] = plateau[8][4].p = new PionSoldat(IJoueur.NOIR, 0, 0, 0, 0, plateau[8][4], this);
		pionsNoirs[10] = plateau[0][5].p = new PionSoldat(IJoueur.NOIR, 0, 3, 2, 0, plateau[0][5], this);
		pionsNoirs[11] = plateau[8][5].p = new PionSoldat(IJoueur.NOIR, 0, 0, 2, 3, plateau[8][5], this);
		pionsNoirs[12] = plateau[4][7].p = new PionSoldat(IJoueur.NOIR, 0, 4, 0, 4, plateau[4][7], this);
		pionsNoirs[13] = plateau[3][8].p = new PionSoldat(IJoueur.NOIR, 3, 0, 0, 2, plateau[3][8], this);
		pionsNoirs[14] = plateau[4][8].p = new PionSoldat(IJoueur.NOIR, 0, 0, 0, 0, plateau[4][8], this);
		pionsNoirs[15] = plateau[5][8].p = new PionSoldat(IJoueur.NOIR, 3, 2, 0, 0, plateau[5][8], this);
		
		pionsBlancs[0] = plateau[4][2].p = new PionSoldat(IJoueur.BLANC, 0, 4, 0, 4, plateau[4][2], this);
		pionsBlancs[1] = plateau[4][3].p = new PionSoldat(IJoueur.BLANC, 0, 3, 0, 3, plateau[4][3], this);
		pionsBlancs[2] = plateau[2][4].p = new PionSoldat(IJoueur.BLANC, 4, 0, 4, 0, plateau[2][4], this);
		pionsBlancs[3] = plateau[3][4].p = new PionSoldat(IJoueur.BLANC, 3, 0, 3, 0, plateau[3][4], this);
		pionsBlancs[4] = plateau[4][4].p = new PionRoi(0, 0, 0, 0, plateau[4][4], this);
		pionsBlancs[5] = plateau[5][4].p = new PionSoldat(IJoueur.BLANC, 3, 0, 3, 0, plateau[5][4], this);
		pionsBlancs[6] = plateau[6][4].p = new PionSoldat(IJoueur.BLANC, 4, 0, 4, 0, plateau[6][4], this);
		pionsBlancs[7] = plateau[4][5].p = new PionSoldat(IJoueur.BLANC, 0, 3, 0, 3, plateau[4][5], this);
		pionsBlancs[8] = plateau[4][6].p = new PionSoldat(IJoueur.BLANC, 0, 4, 0, 4, plateau[4][6], this);
		
		// Des pions inertes, sans couleur, qui servent à exprimer la contrainte des coins interdits
		plateau[0][0].p = new PionInerte(0, 2, 2, 0, plateau[0][0], this);
		plateau[8][0].p = new PionInerte(0, 0, 2, 2, plateau[8][0], this);
		plateau[0][8].p = new PionInerte(2, 2, 0, 0, plateau[0][8], this);
		plateau[8][8].p = new PionInerte(2, 0, 0, 2, plateau[8][8], this);
		
		carte = new CarteInfluence(this);
		
		System.out.println("### Plateau initialisé ! ###");
	}
	
	
	
	// Joue le coup en paramètre en maintenant un historique des pions modifiés
	public void jouerCoupAvecHisto(Coup coup) {
		Pion tmpPion;
		
		// On garde un historique pour le pion du coup ainsi que les pions verticaux et horizontaux qui seront inévitablement modifiés
		coup.historique.ajouterElemHisto(coup.p);
		coup.historique.ajouterElemHisto(coup.p.getPionParCalc(Pion.HAUT));
		coup.historique.ajouterElemHisto(coup.p.getPionParCalc(Pion.DROITE));
		coup.historique.ajouterElemHisto(coup.p.getPionParCalc(Pion.BAS));
		coup.historique.ajouterElemHisto(coup.p.getPionParCalc(Pion.GAUCHE));
		
		// Un code différent est exécuté selon la direction du coup
		switch(coup.direc) {
			case Pion.HAUT:	// Dans le cas d'un MOUVEMENT VERS LE HAUT
				coup.p.relierVoisins(true);	// On met à jour les voisins "horizontaux"
				
				// On met à jour les voisins "verticaux" ainsi que les distMax verticales du pion courant
				tmpPion = coup.p.getPionParCalc(Pion.HAUT);
				if(tmpPion != null)
					tmpPion.distMax[Pion.BAS] -= coup.dist;
				coup.p.distMax[Pion.HAUT] -= coup.dist;
				tmpPion = coup.p.getPionParCalc(Pion.BAS);
				if(tmpPion != null)
					tmpPion.distMax[Pion.HAUT] += coup.dist;
				coup.p.distMax[Pion.BAS] += coup.dist;
				
				// On met à jour la position du pion courant
				coup.p.cas.p = null;
				coup.p.cas = plateau[coup.p.cas.x][coup.p.cas.y-coup.dist];
				coup.p.cas.p = coup.p;
				coup.p.sInsererAvecHisto(true, coup.historique);	// On "insère" le Pion entre les deux autres sur la même ligne
				
				// Si un pion est susceptible d'être supprimé en haut
				if(coup.p.cas.y > 1) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y-1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.BAS)) {
						// Encore un historique 
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						tmpPion.relierVoisins(false);	// mise à jour des voisins verticaux
						
						// Historique des pions horizontaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);	// En mettant à jour les voisins horizontaux
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé à gauche
				if(coup.p.cas.x > 1) {
					tmpPion = plateau[coup.p.cas.x-1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.DROITE)) {
						// Historique du pion à gauche de celui mangé
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						tmpPion.relierVoisins(true);
						
						// Historique des pions verticaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé à droite
				if(coup.p.cas.x < 7) {
					tmpPion = plateau[coup.p.cas.x+1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.GAUCHE)) {
						// Historique du pion à droite de celui mangé
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						tmpPion.relierVoisins(true);
						
						// Historique des pions verticaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
			break;
			case Pion.DROITE:	// Dans le cas d'un MOUVEMENT VERS LA DROITE
				coup.p.relierVoisins(false);	// On met à jour les voisins "verticaux"
				
				// On met à jour les voisins "horizontaux" ainsi que les distMax horizontales du pion courant
				tmpPion = coup.p.getPionParCalc(Pion.GAUCHE);
				if(tmpPion != null)
					tmpPion.distMax[Pion.DROITE] += coup.dist;
				coup.p.distMax[Pion.GAUCHE] += coup.dist;
				tmpPion = coup.p.getPionParCalc(Pion.DROITE);
				if(tmpPion != null)
					tmpPion.distMax[Pion.GAUCHE] -= coup.dist;
				coup.p.distMax[Pion.DROITE] -= coup.dist;
				
				// On met à jour la position du pion courant
				coup.p.cas.p = null;
				coup.p.cas = plateau[coup.p.cas.x+coup.dist][coup.p.cas.y];
				coup.p.cas.p = coup.p;
				coup.p.sInsererAvecHisto(false, coup.historique);	// On "insère" le Pion entre les deux autres sur la même colonne
				
				// Si un pion est susceptible d'être supprimé à droite
				if(coup.p.cas.x < 7) {
					tmpPion = plateau[coup.p.cas.x+1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.GAUCHE)) {
						
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						tmpPion.relierVoisins(true);
						
						// Historique des pions verticaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé en haut
				if(coup.p.cas.y > 1) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y-1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.BAS)) {
						// Historique du pion au dessus de celui mangé
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						tmpPion.relierVoisins(false);
						
						// Historique des pions horizontaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé en bas
				if(coup.p.cas.y < 7) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y+1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.HAUT)) {
						// Historique du pion en dessous de celui mangé
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						tmpPion.relierVoisins(false);
						
						// Historique des pions horizontaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
			break;
			case Pion.BAS:	// Dans le cas d'un MOUVEMENT VERS LE BAS
				coup.p.relierVoisins(true);	// On met à jour les voisins "horizontaux"
				
				// On met à jour les voisins "verticaux" ainsi que les distMax verticales du pion courant
				tmpPion = coup.p.getPionParCalc(Pion.HAUT);
				if(tmpPion != null)
					tmpPion.distMax[Pion.BAS] += coup.dist;
				coup.p.distMax[Pion.HAUT] += coup.dist;
				tmpPion = coup.p.getPionParCalc(Pion.BAS);
				if(tmpPion != null)
					tmpPion.distMax[Pion.HAUT] -= coup.dist;
				coup.p.distMax[Pion.BAS] -= coup.dist;
				
				// On met à jour la position du pion courant
				coup.p.cas.p = null;
				coup.p.cas = plateau[coup.p.cas.x][coup.p.cas.y+coup.dist];
				coup.p.cas.p = coup.p;
				coup.p.sInsererAvecHisto(true, coup.historique);	// On "insère" le Pion entre les deux autres sur la même ligne
				
				// Si un pion est susceptible d'être supprimé en bas
				if(coup.p.cas.y < 7) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y+1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.HAUT)) {
						
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						tmpPion.relierVoisins(false);
						
						// Historique des pions horizontaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé à gauche
				if(coup.p.cas.x > 1) {
					tmpPion = plateau[coup.p.cas.x-1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.DROITE)) {
						// Historique du pion à gauche de celui mangé
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						tmpPion.relierVoisins(true);
						
						// Historique des pions verticaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé à droite
				if(coup.p.cas.x < 7) {
					tmpPion = plateau[coup.p.cas.x+1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.GAUCHE)) {
						// Historique du pion à droite de celui mangé
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						tmpPion.relierVoisins(true);
						
						// Historique des pions verticaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
			break;
			case Pion.GAUCHE:	// Dans le cas d'un mouvement vers la gauche
				coup.p.relierVoisins(false);	// On met à jour les voisins "verticaux"
				
				// On met à jour les voisins "horizontaux" ainsi que les distMax horizontales du pion courant
				tmpPion = coup.p.getPionParCalc(Pion.GAUCHE);
				if(tmpPion != null)
					tmpPion.distMax[Pion.DROITE] -= coup.dist;
				coup.p.distMax[Pion.GAUCHE] -= coup.dist;
				tmpPion = coup.p.getPionParCalc(Pion.DROITE);
				if(tmpPion != null)
					tmpPion.distMax[Pion.GAUCHE] += coup.dist;
				coup.p.distMax[Pion.DROITE] += coup.dist;
				
				// On met à jour la position du pion courant
				coup.p.cas.p = null;
				coup.p.cas = plateau[coup.p.cas.x-coup.dist][coup.p.cas.y];
				coup.p.cas.p = coup.p;
				coup.p.sInsererAvecHisto(false, coup.historique);	// On "insère" le Pion entre les deux autres sur la même colonne
				
				// Si un pion est susceptible d'être supprimé à gauche
				if(coup.p.cas.x > 1) {
					tmpPion = plateau[coup.p.cas.x-1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.DROITE)) {
						
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						tmpPion.relierVoisins(true);
						
						// Historique des pions verticaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé en haut
				if(coup.p.cas.y > 1) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y-1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.BAS)) {
						// Historique du pion au dessus de celui mangé
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.HAUT));
						tmpPion.relierVoisins(false);
						
						// Historique des pions horizontaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé en bas
				if(coup.p.cas.y < 7) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y+1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.HAUT)) {
						// Historique du pion en dessous de celui mangé
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.BAS));
						tmpPion.relierVoisins(false);
						
						// Historique des pions horizontaux
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.GAUCHE));
						coup.historique.ajouterElemHisto(tmpPion.getPionParCalc(Pion.DROITE));
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
			break;
		}
		
		carte.recalculerCarte(coup);
	}
	
	/* Joue le coup en paramètre sans maintenir d'historique. Utilisée pour les coups de l'ennemi.
	 * C'est exactement la même fonction que la précédente
	 */
	public void jouerCoupSansHisto(Coup coup) {
		Pion tmpPion;
		
		// Un code différent est exécuté selon la direction du coup
		switch(coup.direc) {
			case Pion.HAUT:	// Dans le cas d'un MOUVEMENT VERS LE HAUT
				coup.p.relierVoisins(true);	// On met à jour les voisins "horizontaux"
				
				// On met à jour les voisins "verticaux" ainsi que les distMax verticales du pion courant
				tmpPion = coup.p.getPionParCalc(Pion.HAUT);
				if(tmpPion != null)
					tmpPion.distMax[Pion.BAS] -= coup.dist;
				coup.p.distMax[Pion.HAUT] -= coup.dist;
				tmpPion = coup.p.getPionParCalc(Pion.BAS);
				if(tmpPion != null)
					tmpPion.distMax[Pion.HAUT] += coup.dist;
				coup.p.distMax[Pion.BAS] += coup.dist;
				
				// On met à jour la position du pion courant
				coup.p.cas.p = null;
				coup.p.cas = plateau[coup.p.cas.x][coup.p.cas.y-coup.dist];
				coup.p.cas.p = coup.p;
				coup.p.sInsererSansHisto(true);	// On "insère" le Pion entre les deux autres sur la même ligne
				
				// Si un pion est susceptible d'être supprimé en haut
				if(coup.p.cas.y > 1) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y-1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.BAS)) {
						tmpPion.relierVoisins(false);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé à gauche
				if(coup.p.cas.x > 1) {
					tmpPion = plateau[coup.p.cas.x-1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.DROITE)) {
						tmpPion.relierVoisins(true);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé à droite
				if(coup.p.cas.x < 7) {
					tmpPion = plateau[coup.p.cas.x+1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.GAUCHE)) {
						tmpPion.relierVoisins(true);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
			break;
			case Pion.DROITE:	// Dans le cas d'un MOUVEMENT VERS LA DROITE
				coup.p.relierVoisins(false);	// On met à jour les voisins "verticaux"
				
				// On met à jour les voisins "horizontaux" ainsi que les distMax horizontales du pion courant
				tmpPion = coup.p.getPionParCalc(Pion.GAUCHE);
				if(tmpPion != null)
					tmpPion.distMax[Pion.DROITE] += coup.dist;
				coup.p.distMax[Pion.GAUCHE] += coup.dist;
				tmpPion = coup.p.getPionParCalc(Pion.DROITE);
				if(tmpPion != null)
					tmpPion.distMax[Pion.GAUCHE] -= coup.dist;
				coup.p.distMax[Pion.DROITE] -= coup.dist;
				
				// On met à jour la position du pion courant
				coup.p.cas.p = null;
				coup.p.cas = plateau[coup.p.cas.x+coup.dist][coup.p.cas.y];
				coup.p.cas.p = coup.p;
				coup.p.sInsererSansHisto(false);	// On "insère" le Pion entre les deux autres sur la même colonne
				
				// Si un pion est susceptible d'être supprimé à droite
				if(coup.p.cas.x < 7) {
					tmpPion = plateau[coup.p.cas.x+1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.GAUCHE)) {
						tmpPion.relierVoisins(true);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé en haut
				if(coup.p.cas.y > 1) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y-1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.BAS)) {
						tmpPion.relierVoisins(false);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé en bas
				if(coup.p.cas.y < 7) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y+1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.HAUT)) {
						tmpPion.relierVoisins(false);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
			break;
			case Pion.BAS:	// Dans le cas d'un MOUVEMENT VERS LE BAS
				coup.p.relierVoisins(true);	// On met à jour les voisins "horizontaux"
				
				// On met à jour les voisins "verticaux" ainsi que les distMax verticales du pion courant
				tmpPion = coup.p.getPionParCalc(Pion.HAUT);
				if(tmpPion != null)
					tmpPion.distMax[Pion.BAS] += coup.dist;
				coup.p.distMax[Pion.HAUT] += coup.dist;
				tmpPion = coup.p.getPionParCalc(Pion.BAS);
				if(tmpPion != null)
					tmpPion.distMax[Pion.HAUT] -= coup.dist;
				coup.p.distMax[Pion.BAS] -= coup.dist;
				
				// On met à jour la position du pion courant
				coup.p.cas.p = null;
				coup.p.cas = plateau[coup.p.cas.x][coup.p.cas.y+coup.dist];
				coup.p.cas.p = coup.p;
				coup.p.sInsererSansHisto(true);	// On "insère" le Pion entre les deux autres sur la même ligne
				
				// Si un pion est susceptible d'être supprimé en bas
				if(coup.p.cas.y < 7) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y+1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.HAUT)) {
						tmpPion.relierVoisins(false);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé à gauche
				if(coup.p.cas.x > 1) {
					tmpPion = plateau[coup.p.cas.x-1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.DROITE)) {
						tmpPion.relierVoisins(true);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé à droite
				if(coup.p.cas.x < 7) {
					tmpPion = plateau[coup.p.cas.x+1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.GAUCHE)) {
						tmpPion.relierVoisins(true);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
			break;
			case Pion.GAUCHE:	// Dans le cas d'un mouvement vers la gauche
				coup.p.relierVoisins(false);	// On met à jour les voisins "verticaux"
				
				// On met à jour les voisins "horizontaux" ainsi que les distMax horizontales du pion courant
				tmpPion = coup.p.getPionParCalc(Pion.GAUCHE);
				if(tmpPion != null)
					tmpPion.distMax[Pion.DROITE] -= coup.dist;
				coup.p.distMax[Pion.GAUCHE] -= coup.dist;
				tmpPion = coup.p.getPionParCalc(Pion.DROITE);
				if(tmpPion != null)
					tmpPion.distMax[Pion.GAUCHE] += coup.dist;
				coup.p.distMax[Pion.DROITE] += coup.dist;
				
				// On met à jour la position du pion courant
				coup.p.cas.p = null;
				coup.p.cas = plateau[coup.p.cas.x-coup.dist][coup.p.cas.y];
				coup.p.cas.p = coup.p;
				coup.p.sInsererSansHisto(false);	// On "insère" le Pion entre les deux autres sur la même colonne
				
				// Si un pion est susceptible d'être supprimé à gauche
				if(coup.p.cas.x > 1) {
					tmpPion = plateau[coup.p.cas.x-1][coup.p.cas.y].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.DROITE)) {
						tmpPion.relierVoisins(true);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(false);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé en haut
				if(coup.p.cas.y > 1) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y-1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.BAS)) {
						tmpPion.relierVoisins(false);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
				// Si un pion est susceptible d'être supprimé en bas
				if(coup.p.cas.y < 7) {
					tmpPion = plateau[coup.p.cas.x][coup.p.cas.y+1].p;
					
					if((tmpPion != null) && (coup.p.couleur != tmpPion.couleur) && tmpPion.estEncercle(Pion.HAUT)) {
						tmpPion.relierVoisins(false);
						
						// Suppression propre du pion de la couleur opposée
						tmpPion.relierVoisins(true);
						tmpPion.estSurPlateau = false;
						tmpPion.cas.p = null;
					}
				}
				
			break;
		}
		
		carte.recalculerCarte(coup);
	}
	
	// On annule un coup en utilisant l'historique précédemment modifié par jouerCoupAvecHisto.
	public void annulerCoup(Coup coup) {
		coup.historique.restaurerTout();
		carte.retablirCarte();
	}
	
	// Liste les coups possible pour le plateau courant et la couleur en paramètre.
	public ArrayList<Coup> listeCoupsDispos(int couleurCourante) {
		ArrayList<Coup> liste = new ArrayList<Coup>(30);
		Pion[] listeAVerif;
		Pion pionCour;
		
		if(couleurCourante == IJoueur.NOIR)
			listeAVerif = pionsNoirs;
		else
			listeAVerif = pionsBlancs;
		
		for(int i = 0; i < listeAVerif.length; ++i) {
			pionCour = listeAVerif[i];
			
			if(!pionCour.estSurPlateau)	// On ne liste pas les coups des pions "mangés", logique !
				continue;
			
			// Les vérifications suivantes visent à écarter le trone des déplacements possibles
			if(pionCour.cas.x == 4) {	// Si le pion courant est sur la colonne du trone ...
				if(pionCour.cas.y < 4) {	// ... et au dessus du trone ...
					for(int j = pionCour.cas.y - 1; j >= pionCour.cas.y - pionCour.distMax[Pion.HAUT]; --j)
						liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
					for(int j = pionCour.cas.y + 1; j <= pionCour.cas.y + pionCour.distMax[Pion.BAS]; ++j) {
						if(j != 4)	// ... alors on ne vérifie que lors de l'exploration vers le bas
							liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
					}
					for(int j = pionCour.cas.x - 1; j >= pionCour.cas.x - pionCour.distMax[Pion.GAUCHE]; --j)
						liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
					for(int j = pionCour.cas.x + 1; j <= pionCour.cas.x + pionCour.distMax[Pion.DROITE]; ++j)
						liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
				}
				else {	// ... et en dessous du trone ...
					for(int j = pionCour.cas.y - 1; j >= pionCour.cas.y - pionCour.distMax[Pion.HAUT]; --j) {
						if(j != 4)	// ... alors on ne vérifie que lors de l'exploration vers le haut
							liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
					}
					for(int j = pionCour.cas.y + 1; j <= pionCour.cas.y + pionCour.distMax[Pion.BAS]; ++j)
						liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
					for(int j = pionCour.cas.x - 1; j >= pionCour.cas.x - pionCour.distMax[Pion.GAUCHE]; --j)
						liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
					for(int j = pionCour.cas.x + 1; j <= pionCour.cas.x + pionCour.distMax[Pion.DROITE]; ++j)
						liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
				}
			}
			else if(pionCour.cas.y == 4) {	// Sinon si le pion courant est sur la ligne du trone ...
				if(pionCour.cas.x < 4) {	// ... et vers la gauche du trone ...
					for(int j = pionCour.cas.y - 1; j >= pionCour.cas.y - pionCour.distMax[Pion.HAUT]; --j)
						liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
					for(int j = pionCour.cas.y + 1; j <= pionCour.cas.y + pionCour.distMax[Pion.BAS]; ++j)
						liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
					for(int j = pionCour.cas.x - 1; j >= pionCour.cas.x - pionCour.distMax[Pion.GAUCHE]; --j)
						liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
					for(int j = pionCour.cas.x + 1; j <= pionCour.cas.x + pionCour.distMax[Pion.DROITE]; ++j) {
						if(j != 4)	// ... alors on ne vérifie que lors de l'exploration vers la droite
							liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
					}
				}
				else {	// ... et vers la droite du trone ...
					for(int j = pionCour.cas.y - 1; j >= pionCour.cas.y - pionCour.distMax[Pion.HAUT]; --j)
						liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
					for(int j = pionCour.cas.y + 1; j <= pionCour.cas.y + pionCour.distMax[Pion.BAS]; ++j)
						liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
					for(int j = pionCour.cas.x - 1; j >= pionCour.cas.x - pionCour.distMax[Pion.GAUCHE]; --j) {
						if(j != 4)	// ... alors on ne vérifie que lors de l'exploration vers la gauche
							liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
					}
					for(int j = pionCour.cas.x + 1; j <= pionCour.cas.x + pionCour.distMax[Pion.DROITE]; ++j)
						liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
				}
			}
			else {	// Dans tous les autres cas (x et y != 4), il n'y a pas à vérifier.
				for(int j = pionCour.cas.y - 1; j >= pionCour.cas.y - pionCour.distMax[Pion.HAUT]; --j)
					liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
				for(int j = pionCour.cas.y + 1; j <= pionCour.cas.y + pionCour.distMax[Pion.BAS]; ++j)
					liste.add(new Coup(pionCour, pionCour.cas.x, j, this, new Historique()));
				for(int j = pionCour.cas.x - 1; j >= pionCour.cas.x - pionCour.distMax[Pion.GAUCHE]; --j)
					liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
				for(int j = pionCour.cas.x + 1; j <= pionCour.cas.x + pionCour.distMax[Pion.DROITE]; ++j)
					liste.add(new Coup(pionCour, j, pionCour.cas.y, this, new Historique()));
			}
			
			//System.out.println(pionCour.cas.x + " " + pionCour.cas.y + " | " + pionCour.distMax[0] + " " + pionCour.distMax[1] + " " + pionCour.distMax[2] + " " + pionCour.distMax[3] + " ");
		}
		
		return liste;
	}
	
	public void affichay() {	// Pour afficher le plateau si on le désire, utile pour le debuggage
		for(int i = 0; i < 9; i++) {
			for(int j = 0; j < 9; j++) {
				if(plateau[j][i].p != null)
					System.out.print(plateau[j][i].p.couleur + " ");
				else
					System.out.print(". ");
			}
			System.out.print("\n");
		}
		System.out.print("\n");
	}
}
